package simtester.agent

import groovy.time.TimeCategory
import groovy.time.TimeDuration
import groovyx.net.http.RESTClient
import java.util.logging.Logger

class RESTCli extends RESTClient {
    Logger log = Logger.getLogger("simtester.agent")
    def testcaseId
    def user
    def iter
    
    RESTCli(Map args = [:]) {
        super()
    }
    
    RESTCli(Map args = [:], uri) {
        super(uri)
    }

    RESTCli(Map args = [:], uri, contentType) {
        super(uri, contentType)
        testcaseId = args.testcaseId
        user       = args.user
        iter       = args.iter
    }

    def get(Map<String,?> args) {
        makeRequestWithLog('GET', args)
    }
    
    def fakeget(Map<String,?> args) {
        makeRequestWithLog('fakeget', args)
    }
    
    def put(Map<String,?> args) {
        makeRequestWithLog('PUT', args)
    }
    
    def fakeput(Map<String,?> args) {
        makeRequestWithLog('fakeput', args)
    }
    
    def post(Map<String,?> args) {
        makeRequestWithLog('POST', args)
    }
    
    def fakepost(Map<String,?> args) {
        makeRequestWithLog('fakepost', args)
    }
    
    def fakedelete(Map<String,?> args) {
        makeRequestWithLog('fakedelete', args)
    }
    
    def postNoLog(Map<String,?> args) {
        super.post(args)
    }
    
    void capture(String from, String to, Closure closure) {
        def resp = captureResp(type: 'POST', path: from, action: closure)
        
        Random rand = new Random()
        resp = resp * 0.4 + rand.nextInt(50)
        resp = resp.toInteger()
        sleep resp
        captureResp(type: 'GET', path: to, resp: resp)
    }
    
    void capture(String path = '', Closure closure) {
        captureResp(type: 'GET', path: path, action: closure)
    }
    
    private def captureResp(args) {
        def type = args.type ?: 'GET'
        
        if (args.resp) {
            createLogEntry(path: args.path, resp: args.resp, type: type)
            return args.resp
        }
        
        long start
        long end
        try {
            start = System.currentTimeMillis()
            args.action.call()
            end = System.currentTimeMillis()
        } finally {
            def resp
            if (end) {
                resp = end - start
            }
            createLogEntry(path: args.path, resp: resp, type: type)
            return resp
        }
    }
    
    private def makeRequestWithLog(String type, Map<String,?> args) {
        Map<String,?> myargs = [
            path: args.path,
            body: args.body ?: null
        ]

        long start
        long end
        def response
        try {
            start = System.currentTimeMillis()

            if (type == 'GET') {
                response = super.get(args)
                end = System.currentTimeMillis()
            } else if (type == 'PUT') {
                response = super.put(args)
                end = System.currentTimeMillis()
            } else if (type == 'POST') {
                response = super.post(args)
                end = System.currentTimeMillis()
            } else if (type =~ /^fake/) {
                type = type.replaceFirst("fake", "").toUpperCase()
                Random rand = new Random()
                end = start + 50 + rand.nextInt(100)
            }

            return response
        } finally {
            myargs.type = type
            
            if (end) {
                myargs.resp = end - start
            }
            createLogEntry(myargs)
        }
    }
    
    private void createLogEntry(args) {
        StringBuilder msg = new StringBuilder(256)
        if (testcaseId) {
            msg.append('tc:')
            msg.append(testcaseId)
            msg.append(' ')
        }
        
        if (user) {
            msg.append('user:')
            msg.append(user)
        }
        
        if (iter) {
            msg.append(' iter:')
            msg.append(iter)
            msg.append(' ')
        }
        
        if (args.resp) {
            msg.append('resp:')
            msg.append(args.resp)
            msg.append(' ')
        }
        
        msg.append('type:')
        msg.append(args.type)
        msg.append('|')
        msg.append(this.uri)

        if (args.path) {
            msg.append(args.path)
        }

        if (args.body) {
            msg.append(' body:')
            msg.append(args.body.toString())
        }
        
        msg.append(' content-type:')
        msg.append(this.contentType)
        log.info(msg.toString())
    }
}
